package model.network.netty

import cn.hutool.core.lang.UUID
import cn.hutool.core.util.IdUtil
import com.google.gson.Gson
import io.netty.bootstrap.Bootstrap
import io.netty.buffer.Unpooled
import io.netty.channel.Channel
import io.netty.channel.EventLoopGroup
import io.netty.channel.nio.NioEventLoopGroup
import io.netty.channel.socket.DatagramPacket
import io.netty.channel.socket.nio.NioDatagramChannel
import io.netty.util.CharsetUtil
import io.netty.util.internal.SocketUtils
import model.dto.MessageDTO
import model.dto.MsgContentItem
import model.dto.NettyUdpDto
import model.enums.MsgContentItemType
import model.enums.NettyUdpPackageType
import model.repository.MessageRepository
import model.repository.UserRepository
import model.vo.MessageContentItem
import ui.home.HomeViewModel
import ui.search.SearchViewModel
import java.text.SimpleDateFormat
import java.time.LocalDateTime
import java.util.*


/**
 * @author wei kunJie
 * @date 2024/4/16 20:55:51
 */
object NettyClient {
    @Volatile
    var isStart: Boolean = false
    val group: EventLoopGroup = NioEventLoopGroup()
    val host: String = "127.0.0.1"
    val port: Int = 9001
    var channel: Channel? = null

    fun startClient() {
        if (isStart) return
        Thread {
            startNettyClient()
        }.start()
    }

    private val quoteOfTheMomentClientHandler = QuoteOfTheMomentClientHandler()

    fun setHomeViewModel(viewModel: HomeViewModel) {
        quoteOfTheMomentClientHandler.setHomeViewModel(viewModel)
    }

    private fun startNettyClient() {
        try {
            val b = Bootstrap()
            b.group(group).channel(NioDatagramChannel::class.java)
                .handler(quoteOfTheMomentClientHandler)
            // 发送数据包到指定的服务端
            channel = b.connect(host, port).sync().channel()
            var i = 0
            while (true) {
                val nettyUdpDto = NettyUdpDto()
                nettyUdpDto.type = NettyUdpPackageType.GET_MSG
                nettyUdpDto.token = UserRepository.token
                channel?.writeAndFlush(
                    DatagramPacket(
                        Unpooled.copiedBuffer(Gson().toJson(nettyUdpDto), CharsetUtil.UTF_8),
                        SocketUtils.socketAddress(host, port)
                    )
                )
                try {
                    Thread.sleep(1000)
                } catch (e: InterruptedException) {
                    channel?.close()
                    throw RuntimeException(e)
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
        } finally {
            group.shutdownGracefully()
        }
    }

    fun sendTextMsg(messageContentItem: MessageContentItem, toAccount:String, isGroup:Boolean) {
        val msgContentItem= MsgContentItem(
            type =MsgContentItemType.text,
            context = messageContentItem.content
        )
        val nettyUdpDto = NettyUdpDto()
        nettyUdpDto.messageDTO = MessageDTO(
            id = messageContentItem.id,//雪花id
            time = messageContentItem.time,
            contentItemList = listOf(msgContentItem),
            userToken = UserRepository.token,
            userName = UserRepository.user?.username,
            userAvatar = UserRepository.user?.avatar,
            toUserAccount = toAccount,
            isGroup = isGroup,
        )
        nettyUdpDto.type = NettyUdpPackageType.SEND_MSG
        nettyUdpDto.token = UserRepository.token
        //保存正在发送的消息
        MessageRepository.sendingMessageMap[nettyUdpDto.messageDTO?.id.toString()] = nettyUdpDto.messageDTO!!
        channel?.writeAndFlush(
            DatagramPacket(
                Unpooled.copiedBuffer(Gson().toJson(nettyUdpDto), CharsetUtil.UTF_8),
                SocketUtils.socketAddress(host, port)
            )
        )
    }
}